package com.example.demo.utils;

import com.example.demo.model.BaseRowData;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author linjingze
 * @date 2023/11/23 11:02 上午
 */
public class ExcelUtils {

    public static void writeRow(XSSFSheet sheet, XSSFCellStyle cellStyle, List<BaseRowData> rowDataList) {
        Map<Integer, List<BaseRowData>> rowMap = rowDataList.stream().collect(Collectors.groupingBy(BaseRowData::getExRow));
        List<CellRangeAddressInfo> cellRangeAddressList = new ArrayList<>();
        for (Map.Entry<Integer, List<BaseRowData>> e : rowMap.entrySet()) {
            Integer startRow = e.getKey();
            List<BaseRowData> headList = e.getValue();
            XSSFRow row = sheet.createRow(startRow);
            Short height = headList.get(0).getHeight();
            if (height != null) {
                row.setHeightInPoints(height);
            }
            for (BaseRowData exHead : headList) {
                int exColumn = exHead.getExColumn();
                sheet.setColumnWidth(exColumn, 3500);
                XSSFCell cell = row.createCell(exColumn);
                String name = exHead.getName();
                if (exHead.getCellStyle() != null) {
                    cell.setCellStyle(exHead.getCellStyle());
                }else {
                    cell.setCellStyle(cellStyle);
                }
                if (exHead.needMergeColumn()) {
                    for (int i = 1; i <= exHead.getMergeColumn(); i++) {
                        row.createCell(exColumn + 1);
                    }

                    CellRangeAddress region = new CellRangeAddress(startRow,
                            startRow + exHead.getMergeRow(), exColumn, exColumn + exHead.getMergeColumn());
                    sheet.addMergedRegion(region);
                    cellRangeAddressList.add(new CellRangeAddressInfo(name, region, cell.getCellStyle()));
                }
                if (exHead.needMergeRow()) {
                    CellRangeAddress cellRangeAddress = new CellRangeAddress(startRow,
                            startRow + exHead.getMergeRow(), exColumn, exColumn + exHead.getMergeColumn());
                    sheet.addMergedRegion(cellRangeAddress);
                    cellRangeAddressList.add(new CellRangeAddressInfo(name, cellRangeAddress, cell.getCellStyle()));
                }

                setValue(cell, name);
                cell.setCellFormula(exHead.getFormula());
            }
        }
        applyBorderToMergedRegion(cellRangeAddressList, sheet);
    }

    private static void setValue(Cell cell, String name) {
        cell.setCellValue(name);
        if (StringUtils.isNotBlank(name) && name.matches("-?\\d+(\\.\\d+)?([eE][-+]?\\d+)?")) {
            cell.setCellValue(Double.parseDouble(name));
        }
    }

    private static void applyBorderToMergedRegion(List<CellRangeAddressInfo> cellRangeAddressList, Sheet sheet) {
        for (CellRangeAddressInfo cellRangeAddressInfo : cellRangeAddressList) {
            CellRangeAddress cellRangeAddress = cellRangeAddressInfo.getCellRangeAddress();
            String value = cellRangeAddressInfo.getValue();
            CellStyle style = cellRangeAddressInfo.getCellStyle();
            // 设置合并区域的第一个单元格的值和样式
            Row firstRow = sheet.getRow(cellRangeAddress.getFirstRow()) == null ? sheet.createRow(cellRangeAddress.getFirstRow()) : sheet.getRow(cellRangeAddress.getFirstRow());
            Cell firstCell = firstRow.createCell(cellRangeAddress.getFirstColumn());
            firstCell.setCellStyle(style);
            setValue(firstCell, value);
            // 应用边框样式到合并区域的外围
            RegionUtil.setBorderTop(style.getBorderTop(), cellRangeAddress, sheet);
            RegionUtil.setBorderBottom(style.getBorderBottom(), cellRangeAddress, sheet);
            RegionUtil.setBorderLeft(style.getBorderLeft(), cellRangeAddress, sheet);
            RegionUtil.setBorderRight(style.getBorderRight(), cellRangeAddress, sheet);
        }

    }
}
